package com.hunttown.mes.common.utils;

import org.apache.commons.io.IOUtils;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * created by hunttown on 2017/7/27
 */
public class ShardingTool {

    public static void main(String[] args) throws Exception {
        /*
        generateUserShardingSchema();
        generateInsBoltShardingSchema();
        generateOrderShardingSchema();
        */
    }

    private static void generateUserShardingSchema() throws Exception {
        String path = "D:\\IdeaProjects\\ins-demo\\ins-user\\.doc\\sql";
        String namePattern = "users";
        String dbName = "users";
        int dbCount = 10;
        int tableCount = 150;
        int tableIndex = 0;
        generateShardingInitSchema(path, namePattern, dbName, dbCount, tableCount, tableIndex);
        generateShardingDropSchema(path, namePattern, dbName, dbCount, tableCount, tableIndex);
    }

    private static void generateOrderShardingSchema() throws Exception {
        String path = "D:\\work\\ins-order\\ins-order-center\\.doc\\sql";
        String namePattern = "orders";
        String dbName = "orders";
        int dbCount = 10;
        int tableCount = 150;
        int tableIndex = 0;
        generateShardingInitSchema(path, namePattern, dbName, dbCount, tableCount, tableIndex);
        generateShardingDropSchema(path, namePattern, dbName, dbCount, tableCount, tableIndex);
    }

    private static void generateInsBoltShardingSchema() throws Exception {
        String path = "D:\\gitsource\\ins_bolt\\.doc\\sql";
        String namePattern = "ins_bolt";
        String dbName = "ins_bolt";
        int dbCount = 10;
        int tableCount = 150;
        int tableIndex = 0;
        generateShardingInitSchema(path, namePattern, dbName, dbCount, tableCount, tableIndex);
        generateShardingDropSchema(path, namePattern, dbName, dbCount, tableCount, tableIndex);
    }


    private static void generateShardingInitSchema(String path, String namePattern, String dbName, int dbCount, int tableCount, int tableIndex) throws IOException {
        File fromSchemaFile = new File(path, "init_" + namePattern + "_schema.sql");
        File toSchemaFile = new File(path, "init_" + namePattern + "_schema_sharding.sql");

        if (toSchemaFile.exists()) {
            System.out.println("请自己先删除/备份该文件");
            return;
        }


        StringBuffer newContent = new StringBuffer();

        FileInputStream fis = null;
        try {
            fis = new FileInputStream(fromSchemaFile);
            String content = IOUtils.toString(fis);
            String tableRegexp = "(create\\s*table\\s*)(\\w+)(\\s*\\([\\s\\S]*?constraint\\s*pk_)(\\w*)(\\s*.*\\s*.*;)";
            String indexRegexp = "(create\\s*\\w*\\s*index\\s*)(\\w+)(\\s*on\\s*)(\\w+)(\\s*\\(\\s*.*;)";
            Pattern tablePattern = Pattern.compile(tableRegexp, Pattern.MULTILINE | Pattern.CASE_INSENSITIVE);
            Pattern indexPattern = Pattern.compile(indexRegexp, Pattern.MULTILINE | Pattern.CASE_INSENSITIVE);
            Matcher tableMatcher = tablePattern.matcher(content);


            int perDbCount = tableCount / dbCount;

            for (int dbIndex = 0; dbIndex < dbCount; dbIndex++) {
                newContent.append("#db" + dbIndex + "\r\n");
                newContent.append("use " + dbName + padding(dbIndex, dbCount) + ";\r\n");
                if (tableIndex == 300) {
                    tableIndex = 0;
                }

                for (; tableIndex < tableCount; tableIndex++) {

                    int tableMatcherIndex = 0;
                    while (tableMatcher.find(tableMatcherIndex)) {
                        tableMatcherIndex = tableMatcher.end();
                        String tableName = tableMatcher.group(2);
                        StringBuffer tableBuffer = new StringBuffer();
                        tableBuffer.append(tableMatcher.group(1));
                        tableBuffer.append(tableName + padding(tableIndex, tableCount));
                        tableBuffer.append(tableMatcher.group(3));
                        tableBuffer.append(tableName + padding(tableIndex, tableCount));
                        tableBuffer.append(tableMatcher.group(5));
                        newContent.append(tableBuffer);
                        newContent.append("\r\n");
                        int indexMatcherIndex = tableMatcherIndex;
                        Matcher indexMatcher = indexPattern.matcher(content);
                        while (indexMatcher.find(indexMatcherIndex)) {
                            String indexTableName = indexMatcher.group(4);
                            if (!indexTableName.equals(tableName)) {
                                break;
                            }
                            StringBuffer indexBuffer = new StringBuffer();
                            indexBuffer.append(indexMatcher.group(1));
                            indexBuffer.append(indexMatcher.group(2).replace(indexTableName, indexTableName + padding(tableIndex, tableCount)));
                            indexBuffer.append(indexMatcher.group(3));
                            indexBuffer.append(indexTableName + padding(tableIndex, tableCount));
                            indexBuffer.append(indexMatcher.group(5));
                            newContent.append(indexBuffer);
                            newContent.append("\r\n");
                            indexMatcherIndex = indexMatcher.end();
                        }

                        newContent.append("\r\n\r\n");
                    }
                    if ((tableIndex + 1) % perDbCount == 0) {
                        tableIndex++;
                        break;
                    }
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            IOUtils.closeQuietly(fis);
        }

        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(toSchemaFile);
            IOUtils.write(newContent, fos);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            IOUtils.closeQuietly(fos);
        }
    }


    private static void generateShardingDropSchema(String path, String namePattern, String dbName, int dbCount, int tableCount, int tableIndex) throws IOException {
        File fromSchemaFile = new File(path, "drop_" + namePattern + "_schema.sql");
        File toSchemaFile = new File(path, "drop_" + namePattern + "_schema_sharding.sql");

        if (toSchemaFile.exists()) {
            System.out.println("请自己先删除/备份该文件");
            return;
        }


        StringBuffer newContent = new StringBuffer();

        FileInputStream fis = null;
        try {
            fis = new FileInputStream(fromSchemaFile);
            String content = IOUtils.toString(fis);
            String dropTableRegexp = "(drop.*\\s*exists\\s*)(\\w*)(\\s*;)";
            Pattern dropTablePattern = Pattern.compile(dropTableRegexp, Pattern.MULTILINE | Pattern.CASE_INSENSITIVE);
            Matcher tableMatcher = dropTablePattern.matcher(content);


            int perDbCount = tableCount / dbCount;

            for (int dbIndex = 0; dbIndex < dbCount; dbIndex++) {
                newContent.append("#db" + dbIndex + "\r\n");
                newContent.append("use " + dbName + padding(dbIndex, dbCount) + ";\r\n");
                if (tableIndex == 300) {
                    tableIndex = 0;
                }

                for (; tableIndex < tableCount; tableIndex++) {

                    int tableMatcherIndex = 0;
                    while (tableMatcher.find(tableMatcherIndex)) {
                        tableMatcherIndex = tableMatcher.end();
                        String tableName = tableMatcher.group(2);
                        StringBuffer tableBuffer = new StringBuffer();
                        tableBuffer.append(tableMatcher.group(1));
                        tableBuffer.append(tableName + padding(tableIndex, tableCount));
                        tableBuffer.append(tableMatcher.group(3));
                        newContent.append(tableBuffer);
                        newContent.append("\r\n");
                    }
                    if ((tableIndex + 1) % perDbCount == 0) {
                        tableIndex++;
                        break;
                    }
                }
                newContent.append("\r\n\r\n");
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            IOUtils.closeQuietly(fis);
        }

        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(toSchemaFile);
            IOUtils.write(newContent, fos);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            IOUtils.closeQuietly(fos);
        }
    }

    private static String padding(int tableIndex, int tableCount) {
        int size = String.valueOf(tableCount).length();
        if (size <= 1) {
            size = 2;
        }
        return "_" + StringUtils.leftPad(String.valueOf(tableIndex), size, "0");
    }
}
